package com.bzyd.cloud.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.bzyd.cloud.fallback.OrderServiceImpl3BlockHandlerClass;
import com.bzyd.cloud.fallback.OrderServiceImpl3FallbackClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * OrderServiceImpl3，测试sentinel链路流控模式
 * Created by Xianyue Dang on 2021/5/30
 */
@Slf4j
@Service
public class OrderServiceImpl3 {
    int i = 0;

    //方式一：直接将限流和降低方法定义在方法中
    @SentinelResource(
            value = "message",
            blockHandler = "blockHandler",//指定发生BlockException异常时进入的方法
            fallback = "fallback"//指定发生Throwable时进入的方法
    )
    public String message() throws FlowException {
        i++;
        if (i % 3 == 0) {
            throw new RuntimeException();
        }else if (i % 2 == 0){
            throw new FlowException("接口被限流");
        }

        return "message";
    }

    //发生BlockException异常时进入的方法
    public String blockHandler(BlockException ex) {
        log.error("{}", ex);
        return "接口被限流或者降级了...";
    }


    public String fallback(Throwable throwable){
        log.error("{}",throwable);
        return "接口发生异常了...";
    }


    //方式二：将限流和降级方法外置到单独的类中
    @SentinelResource(
            value = "message2",
            blockHandlerClass = OrderServiceImpl3BlockHandlerClass.class,
            blockHandler = "blockHandler",//指定发生BlockException异常时进入的方法
            fallbackClass = OrderServiceImpl3FallbackClass.class,
            fallback = "fallback"//指定发生Throwable时进入的方法
    )
    public String message2() throws FlowException {
        i++;
        if (i % 3 == 0) {
            throw new RuntimeException();
        }else if (i % 2 == 0){
            throw new FlowException("接口被限流");
        }

        return "message2";
    }

}
